#include "IPCWndClient.h"

#define IPCHOSTWNDDEFAULTNAME    L"IPCHostWndDefaultServer"
#define MSGLOOPWINDOWREGCLSNAME  L"MsgLoopWindowDefaultRegClass_"

CIPCWndClient::CIPCWndClient(void)
{
    m_bFindWndEveryTime = false;
    m_hHostWindow = NULL;
    m_strHostName = IPCHOSTWNDDEFAULTNAME;

    memset(m_szHostRegClsName, 0, sizeof(m_szHostRegClsName));
    DWORD dwSessionId = 0;
    ProcessIdToSessionId(GetCurrentProcessId(), &dwSessionId);
    wsprintf(m_szHostRegClsName, MSGLOOPWINDOWREGCLSNAME "%d", dwSessionId);
}

CIPCWndClient::CIPCWndClient(const std::wstring& _strName)
{
    m_bFindWndEveryTime = false;
    m_hHostWindow = NULL;
    m_strHostName = _strName;

    memset(m_szHostRegClsName, 0, sizeof(m_szHostRegClsName));
    DWORD dwSessionId = 0;
    ProcessIdToSessionId(GetCurrentProcessId(), &dwSessionId);
    wsprintf(m_szHostRegClsName, MSGLOOPWINDOWREGCLSNAME "%d", dwSessionId);
}

CIPCWndClient::~CIPCWndClient(void)
{
}

void CIPCWndClient::set_connect_host_name(const std::wstring& _strName)
{
    m_strHostName = _strName;
}

void CIPCWndClient::set_host_server_hwnd(HWND hWnd)
{
    m_hHostWindow = hWnd;
    m_bFindWndEveryTime = false;
}

void CIPCWndClient::set_bfind_wnd_every_time(bool b)
{
    m_bFindWndEveryTime = false;
}

LRESULT CIPCWndClient::send_msg_string(const std::string& strMsg, int iMark)
{
    return send_msg_stringA(strMsg, iMark);
}

LRESULT CIPCWndClient::send_msg_string(const std::wstring& strMsg, int iMark)
{
    return send_msg_stringW(strMsg, iMark);
}

LRESULT CIPCWndClient::send_msg_stringW(const std::wstring& strMsg, int iMark)
{
#define _TAGWSTRING_ 34589 
    wchar_t* pBuffer = new wchar_t[strMsg.length() + 2];
    memcpy(pBuffer, strMsg.c_str(), 2 * strMsg.length() + 2);
    pBuffer[strMsg.length()] = 0;

    LRESULT ret = send_buffer(iMark, pBuffer, 2 * (int)strMsg.length() + 1, _TAGWSTRING_);
    delete[] pBuffer;
    return 0;
}

LRESULT CIPCWndClient::send_msg_stringA(const std::string& strMsg, int iMark)
{
#define _TAGASTRING_ 34588
    char* pBuffer = new char[strMsg.length() + 2];
    memcpy(pBuffer, strMsg.c_str(), strMsg.length());
    pBuffer[strMsg.length()] = 0;

    LRESULT ret = send_buffer(iMark, pBuffer, (int)strMsg.length() + 1, _TAGASTRING_);
    delete[] pBuffer;
    return ret;
}

LRESULT CIPCWndClient::send_message(UINT msg, WPARAM wParam, LPARAM lParam)
{
    return send_msg(msg, wParam, lParam, true);
}

LRESULT CIPCWndClient::post_message(UINT msg, WPARAM wParam, LPARAM lParam)
{
    return send_msg(msg, wParam, lParam, false);
}

LRESULT CIPCWndClient::send_msg(UINT msg, WPARAM wParam, LPARAM lParam, bool b_send)
{
    LRESULT ret = 0;
    if (m_hHostWindow && !::IsWindow(m_hHostWindow) && !m_strHostName.empty())
    {
        m_hHostWindow = NULL;
    }
    if (m_hHostWindow == NULL || m_bFindWndEveryTime)
    {
        if (m_strHostName.empty())
        {
            return -2;
        }
        m_hHostWindow = FindWindowW(m_szHostRegClsName, m_strHostName.c_str());
        if (m_hHostWindow == NULL)
        {
            return -3;
        }
    }
    if (b_send) 
    {
        ret = ::SendMessage(m_hHostWindow, msg, wParam, lParam);
    }
    else
    {
        ::PostMessage(m_hHostWindow, msg, wParam, lParam);
    }
    return ret;
}

LRESULT CIPCWndClient::send_buffer(ULONG iMark, PVOID lpData, DWORD iBufferLen, WPARAM wparam)
{
    if (lpData == NULL || iBufferLen <= 0)
    {
        return -1;
    }
    if (m_hHostWindow && !::IsWindow(m_hHostWindow) && !m_strHostName.empty())
    {
        m_hHostWindow = NULL;
    }
    if (m_hHostWindow == NULL || m_bFindWndEveryTime)
    {
        if (m_strHostName.empty())
        {
            return -2;
        }
        m_hHostWindow = FindWindowW(m_szHostRegClsName, m_strHostName.c_str());
        if (m_hHostWindow == NULL)
        {
            return -3;
        }
    }

    // Send the string to server
    COPYDATASTRUCT cds;
    cds.dwData = iMark;
    cds.cbData = iBufferLen;
    cds.lpData = lpData;
    return ::SendMessage(m_hHostWindow, WM_COPYDATA, wparam, (LPARAM)&cds);
}

